package com.probox.common.entity.utils;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.probox.common.entity.vo.file.UploadResultVo;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import com.qiniu.util.UrlSafeBase64;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Component
public class QiniuAdapter {

    /**
     * 七牛的accessKey
     */
    @Value("${qiniu.accessKey}")
    private String accessKey;

    /**
     * 七牛的secretKey
     */
    @Value("${qiniu.secretKey}")
    private String secretKey;

    /**
     * 指定上传的目标资源空间 Bucket 和资源键 Key（key的长度最大为750字节）。有两种格式：
     * ● <bucket>，表示允许用户上传文件到指定的 bucket。在这种格式下文件只能新增，若已存在同名资源上传则会失败。
     * ● <bucket>:<key>，表示只允许用户上传指定 key 的文件。在这种格式下文件默认允许修改，若已存在同名资源则会被覆盖。如果只希望上传指定 key 的文件，并且不允许修改，那么可以将下面的 insertOnly 属性值设为 1。
     */
    @Value("${qiniu.scope}")
    private String scope;

    /**
     * 上传凭证有效截止时间。Unix时间戳，单位为秒。该截止时间为上传完成后，在七牛空间生成文件的校验时间，而非上传的开始时间，一般建议设置为上传开始时间 + ${deadline}，用户可根据具体的业务场景对凭证截止时间进行调整。
     * 此处指当前时间之后多少秒
     */
    @Value("${qiniu.deadline:3600}")
    private Integer deadline;

    /**
     * 限定上传文件大小最大值，单位：字节（Byte）。 超过限制上传文件大小的最大值会被判为上传失败，返回413状态码。
     */
    @Value("${qiniu.fsizeLimit:8388608}")//2 * 1024 * 1024
    private Integer fsizeLimit;

    @Value("${qiniu.savekey.prefix}")
    private String saveKeyPrefix;

    /**
     * 限定上传文件大小最大值，单位：字节（Byte）。超过限制上传文件大小的最大值会被判为上传失败，返回413状态码。
     */
    @Value("${qiniu.mimeLimit:image/*}")
    private String mimeLimit;

    @Value("${qiniu.domain:http://resource.tkmall.tongkeer.com/}")
    private String domain;

    @Value("${qiniu.domains:https://resource.tkmall.tongkeer.com/}")
    private String domains;

    // 密钥配置
    private Auth auth;

    public Auth getAuth() {
        if (auth == null) {
            auth = Auth.create(accessKey, secretKey);
        }
        return auth;
    }

    private UploadManager uploadManager;

    public UploadManager getUploadManager() {
        if (uploadManager == null) {
            uploadManager = new UploadManager(getConfiguration());
        }
        return uploadManager;
    }

    private Configuration c;

    public Configuration getConfiguration() {
        if (c == null) {
            c = new Configuration(Zone.zone2());
        }
        return c;
    }


    public String getDomains() {
        return domains;
    }

    public void setDomains(String domains) {
        this.domains = domains;
    }

    public String getDomain() {
        return this.domain;
    }

    public UploadResultVo getUploadToken() {
        /* 	if (memberId == null) memberId=0L;*/
        Auth auth = Auth.create(accessKey, secretKey);
        Map<String, Object> putPolicy = new HashMap<>();
        putPolicy.put("scope", scope);
        long currentTime = System.currentTimeMillis() / 1000;
        putPolicy.put("deadline", currentTime + deadline);
        putPolicy.put("fsizeLimit", fsizeLimit);
        putPolicy.put("mimeLimit", mimeLimit);

        String json = JSON.toJSONString(putPolicy);
        String encodedPutPolicy = UrlSafeBase64.encodeToString(json);
        String encodedSign = auth.sign(encodedPutPolicy);
        String uploadToken = encodedSign + ":" + encodedPutPolicy;

        UploadResultVo uploadResultVo = new UploadResultVo();
        uploadResultVo.setDomain(domain);
        uploadResultVo.setToken(uploadToken);

        String key = "";
        String sufix = DateFormatUtils.format(new Date(), "yyMMddHHmmss");

        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        key = saveKeyPrefix + uuid + "_" + sufix;
        uploadResultVo.setKey(key);
        return uploadResultVo;
    }

    public UploadResultVo getAllUploadToken(String fileName) {
        /* 	if (memberId == null) memberId=0L;*/
        Auth auth = Auth.create(accessKey, secretKey);
        Map<String, Object> putPolicy = new HashMap<>();
        putPolicy.put("scope", scope);
        long currentTime = System.currentTimeMillis() / 1000;
        putPolicy.put("deadline", currentTime + deadline);
        putPolicy.put("fsizeLimit", fsizeLimit*100);
        putPolicy.put("mimeLimit", "*");

        String json = JSON.toJSONString(putPolicy);
        String encodedPutPolicy = UrlSafeBase64.encodeToString(json);
        String encodedSign = auth.sign(encodedPutPolicy);
        String uploadToken = encodedSign + ":" + encodedPutPolicy;

        UploadResultVo uploadResultVo = new UploadResultVo();
        uploadResultVo.setDomain(domain);
        uploadResultVo.setToken(uploadToken);

        String key = "";
        String sufix = DateFormatUtils.format(new Date(), "yyMMddHHmmss");

        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        key = saveKeyPrefix + uuid + "_" + sufix;
        if (StringUtils.isNotEmpty(fileName)){
            key += fileName.substring(fileName.lastIndexOf("."));
        }
        uploadResultVo.setKey(key);
        return uploadResultVo;
    }

    private String getImageUpToken() {
        Map<String, Object> putPolicy = new HashMap<>();
        putPolicy.put("scope", scope);
        long currentTime = System.currentTimeMillis() / 1000;
        putPolicy.put("deadline", currentTime + deadline);
        putPolicy.put("fsizeLimit", fsizeLimit);
        putPolicy.put("mimeLimit", mimeLimit);

        String json = JSON.toJSONString(putPolicy);
        String encodedPutPolicy = UrlSafeBase64.encodeToString(json);
        String encodedSign = getAuth().sign(encodedPutPolicy);
        String uploadToken = encodedSign + ":" + encodedPutPolicy;
        return uploadToken;
    }

    /**
     * 上传自定义分类的图片文件到七牛
     *
     * @return String 访问路径
     */
    public String upFileToQiNiu(String path, String suffixName, byte[] data) {
        try {
            path = path + suffixName;
            Zone z = Zone.autoZone();
            Configuration c = new Configuration(z);
            c.connectTimeout = 15;
            UploadManager uploadManager = new UploadManager(c);
            Auth auth = Auth.create(accessKey, secretKey);
            String token = auth.uploadToken(scope, path);
            Response response = uploadManager.put(data, path, token);
            if (response.isOK()) {
                return path;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    //获取视频上传token
    public UploadResultVo getVideoUpToken() {
        Auth auth = Auth.create(accessKey, secretKey);
        Map<String, Object> putPolicy = new HashMap<>();
        putPolicy.put("scope", scope);
        long currentTime = System.currentTimeMillis() / 1000;
        putPolicy.put("deadline", currentTime + deadline);
        putPolicy.put("fsizeLimit", 5242880);
        putPolicy.put("mimeLimit", "video/*");

        String json = JSON.toJSONString(putPolicy);
        String encodedPutPolicy = UrlSafeBase64.encodeToString(json);
        String encodedSign = auth.sign(encodedPutPolicy);
        String uploadToken = encodedSign + ":" + encodedPutPolicy;

        UploadResultVo uploadResultVo = new UploadResultVo();
        uploadResultVo.setDomain(domain);
        uploadResultVo.setToken(uploadToken);

        String key = "";
        String sufix = DateFormatUtils.format(new Date(), "yyMMddHHmmss");

        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        key = saveKeyPrefix + uuid + "_" + sufix;
        uploadResultVo.setKey(key);

        return uploadResultVo;
    }

    public String uploadInputStream(String key, InputStream fileStream, String token) {
        if (ObjectUtil.isEmpty(token)) {
            key = saveKeyPrefix + key;
            token = getImageUpToken();
        }
        try {
            Response response = getUploadManager().put(fileStream, key, token, null, null);

            //解析上传成功的结果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            return getDomain() + putRet.key;
        } catch (QiniuException ex) {
            Response r = ex.response;
            System.err.println(r.toString());
            try {
                System.err.println(r.bodyString());
            } catch (QiniuException ex2) {
                return null;
            }
        }
        return null;
    }
}
